﻿using Basic.FormCollect;
using Basic.FormModel.RecordItem;
using Basic.FormModel.UserRecord;
using Basic.FormRemoteModel;
using Basic.FormRemoteModel.UserForm.Model;
using Basic.FormRemoteModel.UserRecord.Model;
using Basic.UserFormService.Calculate.Interface;
using Basic.UserFormService.Interface;
using Basic.UserFormService.Model;
using LinqKit;
using WeDonekRpc.Client;
using WeDonekRpc.Client.Interface;
using WeDonekRpc.Helper;
using FillRecordRow = Basic.FormRemoteModel.UserForm.Model.FillRecordRow;
using WriteRow = Basic.FormRemoteModel.UserRecord.Model.RecordRow;

namespace Basic.UserFormService.Extend
{
    internal class UserFormService : IUserFormService
    {
        private readonly IUserFormBodyService _FormBody;
        private readonly IUserRecordService _RecordService;
        private readonly IUserFormRecordCollect _Record;
        private readonly IUserFormItemCollect _RecordItem;
        private readonly IIocService _Ioc;
        private readonly IFormDefValueCalculate _Calculate;
        private readonly IFormDefStateCalculate _DefState;
        public UserFormService ( IUserFormBodyService formBody,
            IUserFormRecordCollect record,
            IUserFormItemCollect recordItem,
            IUserRecordService recordService,
            IFormDefStateCalculate defState,
            IFormDefValueCalculate calculate,
            IIocService ioc )
        {
            this._DefState = defState;
            this._Calculate = calculate;
            this._RecordService = recordService;
            this._FormBody = formBody;
            this._Record = record;
            this._RecordItem = recordItem;
            this._Ioc = ioc;
        }

        private FormBodyDto _Body;
        private UserFormBody _Form;
        private FormGetArg _Arg;
        private UserRecord _RecordLog;
        private RecordItemDto[] _Items;
        private bool _FillForm ()
        {
            if ( this._Arg.FillValue == null || this._Arg.FillValue.Count == 0 )
            {
                return false;
            }
            RecordSet record = new RecordSet
            {
                FormId = this._Arg.FormId,
                LinkType = this._Arg.LinkType,
                LinkPK = this._Arg.LinkPk.Value,
                EmpId = this._Arg.EmpId,
            };
            record.Table = this._Body.Table.Convert<FormTableDto, RecordTable>(a =>
            {
                if ( a.TableType == FormTableType.单一表单 )
                {
                    WriteRow row = new WriteRow
                    {
                        RowId = 1,
                        Column = new Dictionary<string, object>()
                    };
                    a.Columns.ForEach(c =>
                    {
                        if ( this._Arg.FillValue.TryGetValue(c.Key, out object value) && value != null )
                        {
                            row.Column.Add(c.Column.Name, value);
                        }
                    });
                    if ( row.Column.Count > 0 )
                    {
                        return new RecordTable
                        {
                            Rows = new WriteRow[] { row },
                            TableId = a.Id
                        };
                    }
                    return null;
                }
                else if ( a.TableType == FormTableType.多行列表 )
                {
                    Dictionary<string, object[]> dic = new Dictionary<string, object[]>();
                    int rowNum = 0;
                    a.Columns.ForEach(c =>
                    {
                        if ( this._Arg.FillValue.TryGetValue(c.Key, out object value) && value != null )
                        {
                            IList<object> list = (IList<object>)value;
                            dic.Add(c.Column.Name, list.ToArray());
                            if ( list.Count > rowNum )
                            {
                                rowNum = list.Count;
                            }
                        }
                    });
                    if ( rowNum > 0 )
                    {
                        return new RecordTable
                        {
                            Rows = rowNum.For<WriteRow>(b =>
                            {
                                WriteRow row = new WriteRow
                                {
                                    RowId = b + 1,
                                    Column = new Dictionary<string, object>()
                                };
                                dic.ForEach(a =>
                                {
                                    if ( a.Value.Length > b )
                                    {
                                        row.Column.Add(a.Key, a.Value[b]);
                                    }
                                });
                                return row;
                            }),
                            TableId = a.Id
                        };
                    }
                }
                return null;
            });
            UserRecordDto res = this._RecordService.SetRecord(record);
            this._Items = res.Items;
            this._RecordLog = res;
            this._Form.RecordId = res.Id;
            return true;
        }
        public UserFormBody Get ( FormGetArg arg )
        {
            this._Arg = arg;
            this._Body = this._FormBody.Get(arg.FormId);
            this._Form = this._Body.ConvertMap<FormBodyDto, UserFormBody>();
            if ( arg.LinkPk.HasValue && arg.LinkType.IsNotNull() )
            {
                this._RecordLog = this._Record.Find(arg.FormId, arg.LinkType, arg.LinkPk.Value);
                if ( this._RecordLog == null )
                {
                    if ( !this._FillForm() )
                    {
                        this._Body.Table.ForEach(c =>
                        {
                            if ( c.SourceKey.IsNotNull() )
                            {
                                UserFormTable table = this._Form.Table.Find(a => a.Id == c.Id);
                                this._InitTable(table, c);
                            }
                        });
                        this._Calculate.CalculateForm(this._Body, this._Form);
                        this._DefState.InitColumnState(this._Body, this._Form, this._Arg);
                        this._InitFormula();
                        return this._Form;
                    }
                }
                else if ( !this._RecordLog.IsNull )
                {
                    this._Items = this._RecordItem.Gets<RecordItemDto>(this._RecordLog.Id);
                }
                if ( !this._RecordLog.IsNull )
                {
                    this._Form.RecordId = this._RecordLog.Id;
                    this._Form.Table.ForEach(c =>
                    {
                        if ( c.TableType == FormTableType.单一表单 )
                        {
                            c.Row = new FillRecordRow
                            {
                                Values = this._Items.Where(a => a.TableId == c.Id).ToDictionary(a => a.ColName, a => a.GetValue())
                            };
                        }
                        else
                        {
                            c.Rows = this._Items.Where(a => a.TableId == c.Id).OrderBy(a => a.RowIndex).GroupBy(a => a.RowIndex).Select(c => new FillRecordRowList
                            {
                                RowId = c.Key,
                                Values = c.ToDictionary(a => a.ColName, a => a.GetValue())
                            }).ToArray();
                        }
                    });
                    this._DefState.InitColumnState(this._Body, this._Form, this._Arg);
                    this._Calculate.CalculateForm(this._Body, this._Form);
                }
            }
            this._InitFormula();
            return this._Form;
        }
        private void _InitFormula ()
        {
            if ( this._Body.Formula.Length > 0 )
            {
                this._Form.UserFormula = this._Body.Formula.Convert<ColFormula, UserFormula>(a =>
                {
                    FormTableDto table = this._Body.Table.Find(b => b.Id == a.TableId);
                    if ( a.VarCol.IsNull() && table.TableType == FormTableType.单一表单 )
                    {
                        return null;
                    }
                    return new UserFormula
                    {
                        Name = a.Name,
                        TableId = a.TableId,
                        TableType = table.TableType,
                        ColId = a.ColId,
                        WatchCol = a.VarCol.ConvertAll(c => new FormulaWatchCol
                        {
                            Name = c.Name,
                            TableId = c.TableId,
                            TableType = this._Body.Table.Find(b => b.Id == c.TableId, b => b.TableType),
                            ColId = c.ColId,
                        })
                    };
                });
            }
            if ( this._Body.StateFormula.Length > 0 )
            {
                this._Form.StateFormula = this._Body.StateFormula.Convert<ColFormula, UserFormula>(a =>
                {
                    FormTableDto table = this._Body.Table.Find(b => b.Id == a.TableId);
                    if ( a.VarCol.IsNull() && table.TableType == FormTableType.单一表单 )
                    {
                        return null;
                    }
                    return new UserFormula
                    {
                        Name = a.Name,
                        TableId = a.TableId,
                        TableType = table.TableType,
                        ColId = a.ColId,
                        WatchCol = a.VarCol.ConvertAll(c => new FormulaWatchCol
                        {
                            Name = c.Name,
                            TableId = c.TableId,
                            TableType = this._Body.Table.Find(b => b.Id == c.TableId, b => b.TableType),
                            ColId = c.ColId,
                        })
                    };
                });
            }
        }
        private void _InitTable ( UserFormTable body, FormTableDto table )
        {
            if ( body.TableType == FormTableType.多行列表 )
            {
                IQueryDataFill dataFill = this._Ioc.Resolve<IQueryDataFill>(table.SourceKey);
                FillRecordRow[] rows = dataFill.FillRow(this._Arg, table);
                if ( !table.MergeCol.IsNull() && body.TableSet.RowGenerateMode == TableRowGenerateMode.根据分组数据生成行 && !body.TableSet.FillColumn.IsNull() )
                {
                    List<FillRecordRowList> newRows = new List<FillRecordRowList>(rows.Length * body.TableSet.FillColumn.Length);
                    Dictionary<string, string>[] fill = body.TableSet.FillColumn;
                    int id = 1;
                    rows.ForEach(r =>
                    {
                        fill.ForEach(c =>
                        {
                            FillRecordRowList row = new FillRecordRowList
                            {
                                RowId = id++,
                                Values = new Dictionary<string, object>(r.Values)
                            };
                            c.ForEach(a =>
                            {
                                row.Values.Add(a.Key, a.Value);
                            });
                            newRows.Add(row);
                        });
                    });
                    body.Rows = newRows.ToArray();
                }
                else
                {
                    body.Rows = rows.ConvertAll(c => new FillRecordRowList
                    {
                        RowId = c.RowId,
                        Values = c.Values
                    });
                }
            }
            else
            {
                IFormDataFill dataFill = this._Ioc.Resolve<IFormDataFill>(table.SourceKey);
                body.Row = dataFill.FillRow(this._Arg, table);
            }
        }
    }
}
